package com.dynamic.datasource;

import com.dynamic.datasource.annotation.DSTransactional;
import com.dynamic.datasource.property.GlobalDataSourceProperty;
import com.dynamic.datasource.provider.DataSourceProvider;
import com.dynamic.datasource.provider.DefaultDataSourceProvider;
import com.dynamic.datasource.router.DefaultDataSourceRouter;
import com.dynamic.datasource.transaction.LocalTransactionInterceptor;
import lombok.Data;
import org.springframework.aop.Advisor;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;

import javax.sql.DataSource;

/**
 * @author 王先堂
 * @Description 数据源自动配置
 * @createTime 2022/03/24/ 11:35:00
 */
@Configuration
@EnableConfigurationProperties(GlobalDataSourceProperty.class)
@AutoConfigureBefore(value = DataSourceAutoConfiguration.class, name = "com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure")
@Import(value = {DruidDataSourceConfiguration.class, DynamicDataSourceFactoryAutoConfigure.class})
@ConditionalOnProperty(prefix = GlobalDataSourceProperty.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@Data
public class DynamicDataSourceAutoConfigure {

    private final GlobalDataSourceProperty globalDataSourceProperty;

    public DynamicDataSourceAutoConfigure(GlobalDataSourceProperty property) {
        this.globalDataSourceProperty = property;
    }

    /**
     * 数据源加载器
     */
    @Bean
    public DataSourceProvider dataSourceProvider() {
        return new DefaultDataSourceProvider(globalDataSourceProperty.getDataSource());
    }

    /**
     * 动态数据源
     */
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        DefaultDataSourceRouter dataSourceRouter = new DefaultDataSourceRouter();
        dataSourceRouter.setP6spy(globalDataSourceProperty.getP6spy());
        dataSourceRouter.setSeata(globalDataSourceProperty.getSeata());
        return dataSourceRouter;
    }

    /**
     * 数据源通知拦截
     */
    @Bean
    public Advisor dynamicDatasourceAnnotationAdvisor() {
        AnnotationInterceptor interceptor = new AnnotationInterceptor(true);
        AnnotationAdvisor advisor = new AnnotationAdvisor(interceptor, com.dynamic.datasource.annotation.DataSource.class);
        advisor.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return advisor;
    }

    /**
     * 本地事务通知拦截
     */
    @Bean
    @ConditionalOnProperty(prefix = GlobalDataSourceProperty.PREFIX, name = "seata", havingValue = "false", matchIfMissing = true)
    public Advisor dynamicTransactionAdvisor() {
        LocalTransactionInterceptor interceptor = new LocalTransactionInterceptor();
        return new AnnotationAdvisor(interceptor, DSTransactional.class);
    }
}
